﻿using HalconDotNet;
using System.Collections.Generic;
using System.Windows.Forms;
using Halcon二次开发.Model;
using System.Drawing;
using Halcon二次开发.Model.图像绑定流程图显示;
using Halcon二次开发.Model.自定义控件;
using System.Xml.Linq;
using Halcon二次开发.Model.储放所有单例.储存每个单例界面;
using System.IO;
using System.Threading;
using MvCameraControl;
using System;
using Halcon二次开发.View.相机;
using System.Drawing.Imaging;
using Halcon二次开发.Controller.Controller基类;
using Halcon二次开发.Tools;
using System.Windows.Shapes;
using Rectangle = System.Drawing.Rectangle;

namespace Halcon二次开发.Controller.CamerForm交互
{
    public class CamerFormController
    {
        /// <summary>
        /// 初始路径，保存路径
        /// </summary>
        private string pathImage;
        /// <summary>
        /// 相机界面UI
        /// </summary>
        CamerForm form;
        /// <summary>
        /// SDK图像 补丁 jjh
        /// </summary>
        HObject RunImage;

        public HwindowFlowNodeUrseControl hwindowFlowNode;
        #region 连接相机字段
        /// <summary>
        /// 海康SDK中的DeviceTLayerType是一个枚举类型，用于指定设备层的类型。在海康的SDK中，通过设置不同的
        /// DeviceTLayerType值，可以获取或设置设备的不同属性或执行特定的操作。
        /// </summary>
        readonly DeviceTLayerType enumTLayerType = DeviceTLayerType.MvGigEDevice
            | DeviceTLayerType.MvUsbDevice
            | DeviceTLayerType.MvGenTLGigEDevice
            | DeviceTLayerType.MvGenTLCXPDevice
            | DeviceTLayerType.MvGenTLCameraLinkDevice
            | DeviceTLayerType.MvGenTLXoFDevice;
        /// <summary>
        /// 设备基本信息集合
        /// </summary>
        List<IDeviceInfo> deviceInfoList = new List<IDeviceInfo>();
        /// <summary>
        ///  相机对象
        /// </summary>
        IDevice device = null;

        /// <summary>
        /// 图像路径集合
        /// </summary>
        public List<string> Paths = new List<string>();

        /// <summary>
        /// 实时现实图像的窗口
        /// </summary>
        RealTimeCamerForm realTimeCamerForm;

        bool runPaper = false;

        Action<HImage> runAction;
        #endregion
        #region 控制参数
        public HObject HideOutputImage;
        #endregion
        public CamerFormController(HwindowFlowNodeUrseControl hwindowFlowNode, RealTimeCamerForm realTimeCamerForm, CamerForm form)
        {
            pathImage = $@"..\..\Data\工程文件\{StaicResouce.HwindowFlowNodeUrse.name}工程文件\相机图片数据";
            //创建一个工程下保存图片的路径默认路径
            Directory.CreateDirectory(pathImage);
            this.form = form;
            this.hwindowFlowNode = hwindowFlowNode;
            this.realTimeCamerForm = realTimeCamerForm;
            runAction += Runing;
            //将上一次的相机图片进行赋值
            if (Directory.Exists(pathImage))
            {
                //相机一个工程只有一个相机
                if (File.Exists(pathImage+"\\"+ "CamerTool0.json"))
                {
                    Paths = HelpJsons.Read<string>(pathImage + "\\" + "CamerTool0.json");
                }
                //显示缩放图上去
                foreach (string item in Paths)
                {
                    PictureBox pictureBox = new PictureBox();
                    //创建右击菜单
                    ContextMenuStrip contex = new ContextMenuStrip();
                    pictureBox.Name = item;
                    //增加一个删除选项
                    contex.Items.Add("删除图片", Image.FromFile("..\\..\\Data\\Image\\Exit2.png"));
                    contex.Items[0].Tag = pictureBox;
                    contex.Items[0].Click += CamerFormController_Click;
                    //绑定右击菜单
                    pictureBox.ContextMenuStrip = contex;
                    pictureBox.Image = Image.FromFile(item);
                    pictureBox.SizeMode = PictureBoxSizeMode.Zoom;
                    form.flowLayoutPanel1.Controls.Add(pictureBox);
                }
                if (Paths.Count>0)
                {
                    //先显示一张图像上去
                    HideOutputImage = new HImage(Paths[0]);
                    hwindowFlowNode.hSmartWindowControl1.HalconWindow.DispObj(HideOutputImage);
                    //图像居中
                    hwindowFlowNode.hSmartWindowControl1.SetFullImagePart();
                    form.label1.Text = "图像:共" + Paths.Count + "张";
                    count = 0;
                }
                
            }
        }
        /// <summary>
        /// 图像索引
        /// </summary>
        public int count;
        /// <summary>
        /// 打开文件夹
        /// </summary>
        public void OpenDirectory(TextBox textBox, FlowLayoutPanel panel,Label label) {
            using (FolderBrowserDialog ofd = new FolderBrowserDialog()) {
                this.Paths.Clear();
                // 设置描述文本（可选）  
                ofd.Description = "请选择一个文件夹";
                // 显示对话框  
                // 检查用户是否点击了“确定”  
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    // 用户选择了一个文件夹，获取其路径  
                    string selectedPath = ofd.SelectedPath;

                    string[] paths = Directory.GetFiles(selectedPath);
                    panel.Controls.Clear();
                    Paths.Clear();
                    //向原来的集合中追加图像路径
                    foreach (string item in paths)
                    {
                        //只有支持这些文件格式
                        if (item.Contains("PNG") || item.Contains("png") || item.Contains("jpg") || item.Contains("bmp"))
                        {
                            Paths.Add(item);
                            textBox.AppendText(item);
                        }
                    }
                    if (Paths.Count == 0) return;
                    //将图片路径进行一个保存
                    string imagePaths = pathImage+"\\"+this.form.Text+".json";
                    HelpJsons.Write<string>(Paths, imagePaths);
                    //显示缩放图上去
                    foreach (string item in Paths)
                    {
                        PictureBox pictureBox = new PictureBox();
                        //创建右击菜单
                        ContextMenuStrip contex = new ContextMenuStrip();
                        pictureBox.Name = item;
                        //增加一个删除选项
                        contex.Items.Add("删除图片", Image.FromFile("..\\..\\Data\\Image\\Exit2.png"));
                        contex.Items[0].Tag = pictureBox;
                        contex.Items[0].Click += CamerFormController_Click;
                        //绑定右击菜单
                        pictureBox.ContextMenuStrip = contex;
                        pictureBox.Image = Image.FromFile(item);
                        pictureBox.SizeMode = PictureBoxSizeMode.Zoom;
                        panel.Controls.Add(pictureBox);
                    }
                    //先显示一张图像上去
                    HideOutputImage = new HImage(Paths[0]);
                    hwindowFlowNode.hSmartWindowControl1.HalconWindow.DispObj(HideOutputImage);
                    //图像居中
                    hwindowFlowNode.hSmartWindowControl1.SetFullImagePart();
                    label.Text = "图像:共" + paths.Length + "张";
                    count = 0;
                }
            }
        }
        /// <summary>
        /// 打开文件
        /// </summary>
        public void OpenFile(TextBox textBox,FlowLayoutPanel panel,Label label) {
            this.Paths.Clear();
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "PNG文件|*.png*|JPEG文件|*.jpg*|BMP文件|*.bmp*";
            ofd.Multiselect = true;
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                panel.Controls.Clear();
                //向原来的集合中追加图像路径
                foreach (string item in ofd.FileNames)
                {
                    Paths.Add(item);
                    textBox.AppendText(item);
                }
                //将图片路径进行一个保存
                string imagePaths = pathImage +"\\"+ this.form.Text+".json";
                HelpJsons.Write<string>(Paths, imagePaths);
                //显示缩放图上去
                foreach (string item in Paths)
                {
                    PictureBox pictureBox = new PictureBox();
                    //创建右击菜单
                    ContextMenuStrip contex = new ContextMenuStrip();
                    pictureBox.Name = item;
                    //增加一个删除选项
                    contex.Items.Add("删除图片", Image.FromFile("..\\..\\Data\\Image\\Exit2.png"));
                    contex.Items[0].Tag = pictureBox;
                    contex.Items[0].Click += CamerFormController_Click;
                    //绑定右击菜单
                    pictureBox.ContextMenuStrip = contex;
                    pictureBox.Image = Image.FromFile(item);
                    pictureBox.SizeMode = PictureBoxSizeMode.Zoom;
                    panel.Controls.Add(pictureBox);
                }
                //先显示一张图像上去
                HideOutputImage = new HImage(Paths[0]);
                hwindowFlowNode.hSmartWindowControl1.HalconWindow.DispObj(HideOutputImage);
                //图像居中
                hwindowFlowNode.hSmartWindowControl1.SetFullImagePart();
                //记录一下当前图像
                label.Text = "图像:共" + ofd.FileNames.Length + "张";
                count = 0;
            }
        }

        /// <summary>
        /// 删除按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CamerFormController_Click(object sender, System.EventArgs e)
        {
            ToolStripMenuItem toolStrip = (ToolStripMenuItem)sender;
            PictureBox node = (PictureBox)toolStrip.Tag;
            string path = node.Name;
            //记录删除之前的位置
            int index = node.Parent.Controls.IndexOf(node);
            node.Parent.Controls.Remove(node);
            Paths.Remove(path);
            //要获取对应对象中的count
            hwindowFlowNode.count = index-1;
            //将图片路径进行一个保存
                string imagePaths = pathImage +"\\"+ this.form.Text+".json";
                HelpJsons.Write<string>(Paths, imagePaths);
            (FormDb.Db["Form1"] as Form1).textBox1.AppendText("注意已删除图层!\r\n");
        }
        /// <summary>
        /// 刷新设备集合
        /// </summary>
        /// <param name="deviceBox">combox控件</param>
        /// <returns></returns>
        public List<IDeviceInfo> RefreshDeviceList()
        {
            deviceInfoList.Clear();
            //获取所有相机设备
            int oRet = DeviceEnumerator.EnumDevices(enumTLayerType, out deviceInfoList);
            if (oRet != MvError.MV_OK)
            {
                return null;
            }
            return deviceInfoList;
        }
        /// <summary>
        /// 打开相机设备
        /// </summary>
        /// //相机设备信息
        IEnumValue triggerSelector = null;  // 触发选项
        IEnumValue triggerMode = null;      // 触发模式
        IEnumValue triggerSource = null;    // 触发源
        IEnumValue pixelFormat = null;      // 像素格式 
        IEnumValue triggerActivation = null; //触发极性
        public bool OpenCamer(int index)
        {
            try
            {
                //通过相机设备创建相机对象
                device = DeviceFactory.CreateDevice(deviceInfoList[index]);
                device.StreamGrabber.FrameGrabedEvent += StreamGrabber_FrameGrabedEvent;

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "error");
            }
            //打开连接
            int ok = device.Open();
            if (ok != MvError.MV_OK)
            {
                MessageBox.Show("Open Device fail!" + ok);
                return false;

            }
            //*
            if (device is IGigEDevice)
            {
                //ch: 转换为gigE设备 | en: Convert to Gige device
                IGigEDevice gigEDevice = device as IGigEDevice;
                // ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
                int optionPacketSize;
                int result = gigEDevice.GetOptimalPacketSize(out optionPacketSize);
                if (result != MvError.MV_OK)
                {
                    MessageBox.Show("Warning: Get Packet Size failed!" + result);
                    return false;
                }
                else
                {
                    result = device.Parameters.SetIntValue("GevSCPSPacketSize", (long)optionPacketSize);
                    if (result != MvError.MV_OK)
                    {
                        MessageBox.Show("Warning: Set Packet Size failed!" + result);
                        return false;
                    }
                }
            }
            //回调函数
            device.Parameters.SetEnumValueByString("TriggerMode", "Off");// 触发模式关闭
            int StartResult = device.StreamGrabber.StartGrabbing();//开始采集
            if (StartResult != MvError.MV_OK)
            {
                return false;
            }
            //将设备触发
            //form.comboBox2.Items.Add();
            //触发模式triggerMode
            device.Parameters.GetEnumValue("TriggerMode", out triggerMode);
            //触发选项triggerSelector
            device.Parameters.GetEnumValue("TriggerSelector", out triggerSelector);//AcquisitionStart
            //触发源triggerSource
            device.Parameters.GetEnumValue("TriggerSource", out triggerSource);//Software软触发   Line0;硬触发线路0
            //像素格式
            device.Parameters.GetEnumValue("PixelFormat", out pixelFormat);//8位图
            //触发极性TriggerActivation
            device.Parameters.GetEnumValue("TriggerActivation", out triggerActivation);
            try
            {
                UploadcomboBox();
            }
            catch { }
            return true;
        }
        /// <summary>
        /// 加载相机窗体中的数据
        /// </summary>
        private void UploadcomboBox()
        {
            foreach (var item in triggerMode.SupportEnumEntries)
            {
                form.comboBox2.Items.Add(item.Symbolic.ToString());
                form.comboBox2.SelectedIndex = 0;
            }
            foreach (var item in triggerSelector.SupportEnumEntries)
            {
                form.comboBox3.Items.Add(item.Symbolic.ToString());
                form.comboBox3.SelectedIndex = 0;
            }
            foreach (var item in triggerSource.SupportEnumEntries)
            {
                form.comboBox4.Items.Add(item.Symbolic.ToString());
                form.comboBox4.SelectedIndex = 0;
            }
            foreach (var item in pixelFormat.SupportEnumEntries)
            {
                form.comboBox5.Items.Add(item.Symbolic.ToString());
                form.comboBox5.SelectedIndex = 0;
            }
            foreach (var item in triggerActivation.SupportEnumEntries)
            {
                form.comboBox6.Items.Add(item.Symbolic.ToString());
                form.comboBox6.SelectedIndex = 0;
            }
        }
        /// <summary>
        /// 更改相机属性
        /// </summary>
        //相机硬触发的开启标志位
        public bool triggerModePaper=false;
        //相机硬触发标志位
        public bool triggerSourcePaper = false;
        public void SetCamerMode()
        {
            int modePaper = 0;
            //取消图片线程int StartResult = device.StreamGrabber.StartGrabbing();//开始采集
            int StartResult = device.StreamGrabber.StopGrabbing();//停止采集，只有停止采集了才可以设置这些属性
            //修改触发模式
            //相机触发源
            modePaper = device.Parameters.SetEnumValue("TriggerSource", (uint)triggerSource.SupportEnumEntries[form.comboBox4.SelectedIndex].Value);
            ModeException(modePaper);
            //相机触发模式
            modePaper =device.Parameters.SetEnumValue("TriggerMode", (uint)triggerMode.SupportEnumEntries[form.comboBox2.SelectedIndex].Value);
            ModeException(modePaper);
            //相机触发选项
            modePaper = device.Parameters.SetEnumValue("TriggerSelector", (uint)triggerSelector.SupportEnumEntries[form.comboBox3.SelectedIndex].Value);
            ModeException(modePaper);
            //相机像素格式
            modePaper = device.Parameters.SetEnumValue("PixelFormat", (uint)pixelFormat.SupportEnumEntries[form.comboBox5.SelectedIndex].Value);
            ModeException(modePaper);
            try
            {
                //相机触发极性
                modePaper = device.Parameters.SetEnumValue("TriggerActivation", (uint)triggerActivation.SupportEnumEntries[form.comboBox6.SelectedIndex].Value);
                ModeException(modePaper);
            }
            catch { }
            //标志模式是不是硬触发模式
            if (!triggerSource.SupportEnumEntries[form.comboBox4.SelectedIndex].Symbolic.Equals("Software"))
            {
                triggerSourcePaper = true;
                if (triggerMode.SupportEnumEntries[form.comboBox2.SelectedIndex].Symbolic.Equals("On"))
                {
                    triggerModePaper = true;
                }
                else
                {
                    triggerModePaper = false;
                }
            }
            else
            {
                triggerSourcePaper = false;
            }
            //开始采集
            StartResult = device.StreamGrabber.StartGrabbing();//开始采集
        }
        /// <summary>
        /// 电平反转，输出电信号
        /// </summary>
        public void LevelReversal()
        {
            //只有硬触发时才会进入到这个条件
            if (triggerSourcePaper&& triggerModePaper)
            {
                int modePaper = 0;
                modePaper = device.Parameters.SetBoolValue("LineInverter", true);
                ModeException(modePaper,"输出信号失败,");
                //电平持续时间
                Thread.Sleep((int)form.numericUpDown5.Value);
                modePaper = device.Parameters.SetBoolValue("LineInverter", false);
                ModeException(modePaper, "输出信号失败,");
            }
        }
        /// <summary>
        /// 相机采图访问的回调函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void StreamGrabber_FrameGrabedEvent(object sender, FrameGrabbedEventArgs e)
        {
            //Software   On
            try
            {
                Bitmap bitmap = e.FrameOut.Image.ToBitmap();

                BitmapToHImageBpp32(bitmap, out HImage image, PixelFormat.Format32bppArgb);//最后一个参数指定像素格式
                realTimeCamerForm.hSmartWindowControl1.HalconWindow.DispObj(image);
                realTimeCamerForm.hSmartWindowControl1.SetFullImagePart();
                //给输出图像
                RunImage = image;
                if (triggerModePaper&&triggerSourcePaper)
                {
                    //运行一次最外层Run方法 toolStripButton1_Click(null,null);
                    hwindowFlowNode.toolStripButton1_Click(sender,e);
                }
            }
            catch{}
        }
        /// <summary>
        /// 处理相机配置异常码
        /// </summary>
        /// <param name="modeRunPaper">异常码</param>
        /// <param name="text">可选文本，附加内容</param>
        private void ModeException(int modeRunPaper,string text="")
        {
            if (modeRunPaper!=0)
            {
                (FormDb.Db["Form1"] as Form1).textBox1.AppendText(HelpGetTiem.Getyyymmddmmss()+$": {text}相机配置失败，异常码为:" + ":" + modeRunPaper + "\r\n");
            }
        }
        /// <summary>
        /// 关闭取相
        /// </summary>
        /// <returns></returns>
        public bool CloseCamer()
        {
            try
            {
                int reuslt = device.StreamGrabber.StopGrabbing();
                if (reuslt != MvError.MV_OK)
                {
                    return false;
                }
                else
                {
                    device.Parameters.SetEnumValueByString("TriggerMode", "On");
                    device.Close();
                    device.Dispose();
                    device = null;
                    return true;
                }
            }
            catch
            {
                return true;
            }
        }
        /// <summary>
        /// 运行按钮
        /// </summary>
        public void Run()
        {

            if (form.tabControl1.SelectedIndex == 0)
            {
                //图片
                if (device != null)
                {
                    runPaper = true;
                }
                //文件图像 如果没有图像文件
                if (Paths.Count == 0)
                {
                    throw new Exception("没有图像文件");
                }
                count++;
                //尾部
                if (count == Paths.Count)
                {
                    count = 0;
                }
                //对当前图像对象进行更新 
                HideOutputImage = new HImage(Paths[count]);
            }

            if (form.tabControl1.SelectedIndex == 1)
            {
                if (device == null)
                {
                    throw new Exception("未初始化取相");
                }
                else
                {
                    //相机
                    HideOutputImage = RunImage;
                }
            }
        }
        /// <summary>
        /// 运行后获取图像的委托
        /// </summary>
        /// <param name="obj"></param>
        private void Runing(HImage image)
        {
            runPaper = false;
            HSmartWindowControl hw = StaicResouce.HwindowFlowNodeUrse.hSmartWindowControl1;
            hw.HalconWindow.DispObj(image);
            hw.SetFullImagePart();
        }
        /// <summary>
        /// 当前对象被强行关闭时释放资源
        /// </summary>
        public void Closed()
        {
            try
            {
                if (device != null)
                {
                    device.Parameters.SetEnumValueByString("TriggerMode", "On");
                    device.Close();
                    device.Dispose();
                    device = null;
                }
            }
            catch
            {

            }
        }
        ///<summary>
        /// Bitmap转HImage(32位4通道)
        /// </summary>
        public static void BitmapToHImageBpp32(Bitmap bmp, out HImage image, PixelFormat pixelFormat)
        {
            try
            {

                image = new HImage();
                Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
                BitmapData srcBmpData = bmp.LockBits(rect, ImageLockMode.ReadOnly, pixelFormat);
                image.GenImageInterleaved(srcBmpData.Scan0, "rgbx", bmp.Width, bmp.Height, 0, "byte", bmp.Width, bmp.Height, 0, 0, -1, 0);
                bmp.UnlockBits(srcBmpData);
            }
            catch (Exception ex)
            {
                image = null;
            }
        }
        /// <summary>
        /// 设置曝光
        /// </summary>
        /// <param name="value"></param>
        public void SetExposure(float value)
        {
            try
            {
                if (device != null)
                {
                    device.Parameters.SetEnumValue("AcquisitionFrameRateAuto", 0);
                    int result = device.Parameters.SetFloatValue("AcquisitionFrameRate", value);
                }
            }
            catch
            {

            }

        }
        /// <summary>
        /// 设置增益
        /// </summary>
        /// <param name="value"></param>
        public void SetGain(float value)
        {
            try
            {
                if (device != null)
                {
                    device.Parameters.SetEnumValue("GainAuto", 0);
                    int result = device.Parameters.SetFloatValue("Gain", value);
                }
            }
            catch
            {

            }
        }
        public void SetAcquisitionFrameRate(float value)
        {
            device.Parameters.SetEnumValue("ExposureAuto", 0);
            int result = device.Parameters.SetFloatValue("AcquisitionFrameRate", value);
        }
    }

}
